package p2psvideo;

import android.os.Handler;
import android.os.Message;

import nfwx.analytics.Grab;
import nfwx.analytics.GrabVideoMeta;
import nfwx.analytics.GrabVideoSession;


/**
 * 桥接播放统计系统和P2PSPlayer
 */

public class GrabP2PSPlayerBridge implements Handler.Callback
{
    /**
     * 播放器
     */
    private P2PSPlayer _player;
    /**
     * 是否已经加载
     */
    private boolean _initialized;
    /**
     * 是否在seeking
     */
    private boolean _seeking;

    /**
     * 是否缓冲中
     */
    private boolean _buffering;

    /**
     * 上一次缓冲时获取了status的时间，防止过度频繁的获取status, 原因是status尺寸较大
     */
    private long _lastBufferStatusTime;

    /**
     * 统计会话
     */
    private GrabVideoSession _session;

    /**
     * 用于统计播放时长
     */
    private Handler _handler;

    static final int MSG_PLAY_TIME_HEART_BEAT=100;

    static final int HEART_BEAT_INTERVAL=1000;

    /**
     * 保存会话
     */
    private void save()
    {
        try {
            Grab.getInstance().post(_session);
        } catch(Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化播放器统计会话, 在准备播放新视频前创建这个对象
     * @param url 播放地址
     * @param name 标题, 可选
     * @param player 播放器对象
     */
    public GrabP2PSPlayerBridge(String url, String name, P2PSPlayer player)
    {
        _player = player;
        _session = Grab.getInstance().beginVideoSession(url, name);
    }

    /**
     * 加载成功
     */
    public void loadOK()
    {
        _handler = new Handler(this);
        _handler.sendEmptyMessageDelayed(MSG_PLAY_TIME_HEART_BEAT, HEART_BEAT_INTERVAL);
        _initialized = true;
        //完成加载
        _session.finishLoad(_player.currentPosition(), (long)_player.getTimeCode(), _player.getStatus());
        //获取视频信息
        P2PSMgr.P2PSFileInfo info = _player.getCurrentFileInfo();
        if (info == null) {
            save();
            return;
        }
        GrabVideoMeta meta = _session.meta;
        meta.name.setValue(info.name);
        meta.duration.setValue(info.duration);
        meta.vid.setValue(info.vid);
        meta.vsid.setValue(info.vsid);
        meta.live.setValue(info.live);
        //获取视频子流信息
        if (info.streams == null) {
            save();
            return;
        }
        P2PSMgr.P2PFileSubStreamInfo sinfo = null;
        for(int i=0; i<info.streams.length; ++i) {
            if (info.streams[i].vsid.equals(info.vsid)) {
                sinfo = info.streams[i];
            }
        }
        if (sinfo == null) {
            save();
            return;
        }
        meta.width.setValue(sinfo.width);
        meta.height.setValue(sinfo.height);
        save();
    }

    /**
     * 加载失败
     * @param code 错误码
     * @param msg 错误信息
     */
    public void loadFailed(String code, String msg)
    {
        _session.errorLoad(code, msg, _player.getStatus());
        try {
            Grab.getInstance().endSession(_session);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 告知统计会话正在缓冲，请在setOnBufferUpdate回调中调用
     */
    public void bufferring(int percent)
    {
        if (!_initialized) return;
        if (_seeking || _player.pausing()) return; //加载中和定位中不算

        if (percent < 100) {
            if (_buffering) return;
            _buffering = true;
            long t = System.currentTimeMillis();
            if (t - _lastBufferStatusTime > 30000) {
                _lastBufferStatusTime = t;
                _session.beginRebuffer(_player.currentPosition(), (long)_player.getTimeCode(), _player.getStatus());
            } else {
                _session.beginRebuffer(_player.currentPosition(), (long)_player.getTimeCode(), null);
            }
        } else { //缓冲完成
            if (!_buffering) return;
            _buffering = false;
            _session.endRebuffer();
        }
    }

    /**
     * 告知统计会话执行了暂停
     */
    public void pause()
    {
        if (!_initialized) return;
        _seeking = false;
        _buffering = false;
        _session.pauseEvent(_player.currentPosition(), (long)_player.getTimeCode());
        save();
    }

    /**
     * 告知统计会话执行了暂停恢复
     */
    public void resume()
    {
        if (!_initialized) return;
        _seeking = false;
        _buffering = false;
        _session.resumeEvent(_player.currentPosition(), (long)_player.getTimeCode());
        save();
    }

    /**
     * 告知统计会话执行了seek
     * @param time 目标时间戳
     * @param tc 目标时间码, 如果没有则设置为0
     */
    public void seek(int time, long tc)
    {
        if (!_initialized) return;
        _seeking = true;
        _buffering = false;
        _session.beginSeek(time, tc);
    }

    /**
     * 告知统计会话seek完成
     */
    public void seekComplete()
    {
        if (!_initialized) return;
        if (!_seeking) return;
        _seeking = false;
        _buffering = false;
        _session.endSeek();
        save();
    }

    /**
     * 告知统计会话播放到了结束点
     */
    public void playEnd()
    {
        if (!_initialized) return;
        _seeking = false;
        _buffering = false;
        _session.playEndEvent(_player.currentPosition(), (long)_player.getTimeCode());
        save();
    }

    /**
     * 告知统计会话结束播放, 清理播放器
     */
    public void stop()
    {
        _initialized = false;
        _seeking = false;
        _buffering = false;
        try {
            Grab.getInstance().endSession(_session);
        } catch(Throwable e) {
            e.printStackTrace();
        }
        if (_handler != null) {
            _handler.removeCallbacksAndMessages(null);
            _handler = null;
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        if (msg.what == MSG_PLAY_TIME_HEART_BEAT) {
            if (_handler != null) {
                _handler.removeCallbacksAndMessages(null);
                _handler.sendEmptyMessageDelayed(MSG_PLAY_TIME_HEART_BEAT, HEART_BEAT_INTERVAL);
            }
            if (!_initialized) return false;

            //汇报播放进度
            _session.reportTimeInfo(_player.currentPosition(),(long)_player.getTimeCode());
            //汇报是否无信号
            _session.reportNoSignal(_player.noSignal());
            //判断是否需要计时
            boolean ok=true;
            if (_player.pausing()) { //暂停中不计时
                ok = false;
            }
            if (!_player.playing()) { //非播放中不计时
                ok = false;
            }
            if (_player.isBufferring()) { //缓冲中不计时
                ok = false;
            }
            if (_player.ended()) { //播放结束不计时
                ok = false;
            }
            if (!_player.ready()) { //未就绪不计时
                ok = false;
            }
            //如果需要计时，计时一次
            if (ok) _session.increaseUseTime(HEART_BEAT_INTERVAL);
            //每30秒保存一次
            if (_session.useTimeDelta.getValue() > 30000) {
                save();
            }
        }
        return false;
    }
}
